Multiple DataSource Configuration এর ধারণা
স্প্রিং বুট অ্যাপ্লিকেশনটি সাধারণত একটি ডেটাবেস (DataSource) ব্যবহার করে ডেটা পরিচালনা করে, তবে কখনো কখনো একাধিক ডেটাবেসের সাথে কাজ করার প্রয়োজন হতে পারে। উদাহরণস্বরূপ, আপনি একটি রিলেশনাল ডেটাবেসের সাথে কাজ করছেন, এবং একই অ্যাপ্লিকেশনটিতে নন-রিলেশনাল ডেটাবেস যেমন MongoDB বা Cassandra ব্যবহার করছেন। এছাড়া বিভিন্ন ডেটাবেসের জন্য বিভিন্ন DataSource ব্যবহার করা যেতে পারে, যেমন একটি ডেটাবেস শুধুমাত্র রিড অপারেশনের জন্য, আরেকটি ডেটাবেস রাইট অপারেশনের জন্য ব্যবহার করা হচ্ছে।
স্প্রিং বুটে Multiple DataSources কনফিগারেশন ব্যবহারের মাধ্যমে আপনি একাধিক ডেটাবেস সংযোগের জন্য পৃথক কনফিগারেশন তৈরি করতে পারেন এবং স্প্রিং অ্যাপ্লিকেশনটি বিভিন্ন ডেটাবেসে ডেটা পরিচালনা করতে সক্ষম হয়।
Multiple DataSource Configuration এর প্রয়োজনীয়তা
- বিভিন্ন ডেটাবেস থেকে ডেটা টেনে আনা: একাধিক ডেটাবেস থেকে ডেটা টেনে আনার জন্য আলাদা আলাদা ডেটাবেস সংযোগের প্রয়োজন।
- ট্রানজেকশন ম্যানেজমেন্ট: একাধিক ডেটাবেসের মধ্যে সুনির্দিষ্ট ট্রানজেকশন পরিচালনা করা।
- অধিক পারফরম্যান্স এবং সিস্টেম স্থিতিশীলতা: একাধিক ডেটাবেস ব্যবহার করে সিস্টেমের কাজের চাপ বিভাজন করা।
Multiple DataSource Configuration কনফিগারেশন
স্প্রিং বুটে Multiple DataSource কনফিগারেশন তৈরি করতে হলে আপনাকে কিছু নির্দিষ্ট পদক্ষেপ অনুসরণ করতে হবে।
১. Multiple DataSource Configuration for JPA
ধরা যাক, আপনার একটি অ্যাপ্লিকেশন আছে যেখানে দুটি ডেটাবেস ব্যবহার করা হচ্ছে: একটি ডেটাবেস সাধারণ ডেটা সংরক্ষণের জন্য এবং অন্যটি রেফারেন্স ডেটা পরিচালনা করার জন্য।
১.১. application.properties কনফিগারেশন
# Primary DataSource Configuration
spring.datasource.primary.url=jdbc:mysql://localhost:3306/primary_db
spring.datasource.primary.username=root
spring.datasource.primary.password=root
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
# Secondary DataSource Configuration
spring.datasource.secondary.url=jdbc:mysql://localhost:3306/secondary_db
spring.datasource.secondary.username=root
spring.datasource.secondary.password=root
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
১.২. DataSource Configuration Class
প্রথমেই দুটি DataSource কনফিগার করতে হবে। একটি Primary DataSource এবং একটি Secondary DataSource।
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
@Bean
@Primary
public DataSource primaryDataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
@Bean
public DataSource secondaryDataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
@Bean
@Primary
public PlatformTransactionManager primaryTransactionManager(EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
@Bean
public PlatformTransactionManager secondaryTransactionManager() {
return new DataSourceTransactionManager(secondaryDataSource(null));
}
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory(javax.sql.DataSource dataSource) {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(primaryDataSource(null));
factoryBean.setPackagesToScan("com.example.domain");
return factoryBean;
}
}
ব্যাখ্যা:
@Primary: এটি স্প্রিংকে বলে দেয় যে কোন ডেটাবেস প্রাথমিক ডেটাবেস হবে। এখানেprimaryDataSource()মেথডে প্রাথমিক ডেটাবেসের কনফিগারেশন ব্যবহার করা হয়েছে।secondaryDataSource(): এখানে সেকেন্ডারি ডেটাবেসের কনফিগারেশন প্রদান করা হয়েছে।PlatformTransactionManager: টেলিস্কোপিং ডেটাবেসের ট্রানজেকশন পরিচালনা করার জন্য পৃথক পৃথক ট্রানজেকশন ম্যানেজার তৈরি করা হয়েছে।
১.৩. Repository Configuration
স্প্রিং বুটে দুটি আলাদা ডেটাবেসের জন্য @EnableJpaRepositories অ্যানোটেশন ব্যবহার করতে হবে।
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@Configuration
@ComponentScan(basePackages = "com.example")
@EnableJpaRepositories(
basePackages = "com.example.repository.primary",
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "primaryTransactionManager"
)
public class PrimaryDataSourceConfig {
}
@Configuration
@EnableJpaRepositories(
basePackages = "com.example.repository.secondary",
entityManagerFactoryRef = "secondaryEntityManagerFactory",
transactionManagerRef = "secondaryTransactionManager"
)
public class SecondaryDataSourceConfig {
}
ব্যাখ্যা:
@EnableJpaRepositories: এই অ্যানোটেশনটি স্প্রিংকে বলে দেয় যে কোথা থেকে JPA রেপোজিটরি ক্লাসগুলি লোড করতে হবে এবং কোন EntityManagerFactory এবং ট্রানজেকশন ম্যানেজার ব্যবহার করতে হবে।
২. Service Layer
একটি Service Layer তৈরি করা যেখানে আপনি primary এবং secondary ডেটাবেসের জন্য CRUD অপারেশন পরিচালনা করবেন।
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PersonService {
@Autowired
private PersonRepository primaryRepository;
@Autowired
private AddressRepository secondaryRepository;
public Person savePerson(Person person) {
return primaryRepository.save(person);
}
public Address saveAddress(Address address) {
return secondaryRepository.save(address);
}
}
ব্যাখ্যা:
primaryRepository: এই রেপোজিটরি primary database-এর জন্য তৈরি।secondaryRepository: এই রেপোজিটরি secondary database-এর জন্য তৈরি।
৩. Entity Classes
Entity ক্লাস তৈরি করতে হবে যাতে Primary এবং Secondary ডেটাবেসে সংরক্ষিত ডেটা এক্সপোজ করা যায়।
Primary Entity (Person.java):
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Person {
@Id
private Long id;
private String name;
private int age;
// Getters and Setters
}
Secondary Entity (Address.java):
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Address {
@Id
private Long id;
private String street;
private String city;
// Getters and Setters
}
সারাংশ
স্প্রিং বুটে Multiple DataSource Configuration করা খুব সহজ এবং এটি স্প্রিং কন্টেইনারের মাধ্যমে বিভিন্ন ডেটাবেসের সাথে ইন্টিগ্রেশন করতে সহায়ক। @Primary এবং @EnableJpaRepositories অ্যানোটেশন ব্যবহার করে আপনি ডেটাবেস কনফিগারেশন এবং রেপোজিটরি কনফিগার করতে পারেন। এটি Primary এবং Secondary ডেটাবেসের মধ্যে কার্যকরীভাবে ডেটা ভাগ করা এবং পরিচালনা করার জন্য একটি শক্তিশালী সমাধান প্রদান করে।
এভাবে আপনি একটি স্প্রিং বুট অ্যাপ্লিকেশন ব্যবহার করে একাধিক ডেটাবেসে ডেটা পরিচালনা করতে পারেন, যার মধ্যে পারফরম্যান্স বৃদ্ধি এবং বিভিন্ন ডেটাবেসের নির্দিষ্ট কাজগুলো বিভাজন করা সহজ হয়।
Multiple DataSource কি?
Multiple DataSource হল একটি কনসেপ্ট যেখানে একাধিক ডাটাবেস (যেমন: MySQL, PostgreSQL, MongoDB ইত্যাদি) এক অ্যাপ্লিকেশনে ব্যবহার করা হয়। Spring Boot এর মাধ্যমে আপনি সহজেই একাধিক ডাটাবেসের সাথে যোগাযোগ করতে পারেন, একে বলা হয় Multiple DataSource Configuration।
Spring Boot সাধারণত একটি ডাটাবেস কনফিগারেশন ধারণ করে, কিন্তু কখনো কখনো আমাদের প্রয়োজন হয় একাধিক ডাটাবেস ব্যবহারের, যেমন বিভিন্ন ডেটা ধরনের জন্য আলাদা ডাটাবেস (RDBMS এবং NoSQL), বা একটি অ্যাপ্লিকেশনে বিভিন্ন অঞ্চলের জন্য আলাদা ডাটাবেস ব্যবহার।
Spring Boot-এ Multiple DataSource কনফিগারেশন করার মাধ্যমে আপনি একাধিক ডাটাবেসের সাথে কাজ করতে পারবেন, এবং প্রতিটি ডাটাবেসের জন্য আলাদা EntityManager, TransactionManager, এবং DataSource তৈরি করা সম্ভব।
Multiple DataSource Configuration এর প্রয়োজনীয়তা
- ভিন্ন ভিন্ন ডেটা উৎসের ব্যবহারের প্রয়োজন: অনেক সময় বিভিন্ন ধরণের ডেটার জন্য আলাদা ডাটাবেস ব্যবহারের প্রয়োজন হয়। উদাহরণস্বরূপ, RDBMS এবং NoSQL ডাটাবেস একই অ্যাপ্লিকেশনে ব্যবহৃত হতে পারে।
- একাধিক ডাটাবেসে ডেটার পারফরম্যান্স অপটিমাইজেশন: কিছু নির্দিষ্ট ডেটা প্রয়োজনে RDBMS তে সংরক্ষণ করা যেতে পারে, আবার কিছু ডেটা NoSQL ডাটাবেসে সঞ্চিত হতে পারে। একাধিক ডাটাবেস ব্যবহার করে আপনি বিভিন্ন ডেটার জন্য পারফরম্যান্স অপটিমাইজেশন করতে পারেন।
- ভিন্ন ভিন্ন ডেটা সেন্টার ব্যবহার: একটি অ্যাপ্লিকেশন বিভিন্ন অঞ্চলে চলতে পারে, যেখানে প্রতি অঞ্চলে আলাদা ডাটাবেস ব্যবহার করা হয়।
- টেস্টিং এবং প্রোডাকশন আলাদা ডাটাবেস: কিছু ক্ষেত্রে, টেস্টিং এবং প্রোডাকশনের জন্য আলাদা ডাটাবেস ব্যবহার করা হয়।
Multiple DataSource Configuration উদাহরণ
এখানে একটি Spring Boot অ্যাপ্লিকেশনের উদাহরণ দেওয়া হবে, যেখানে দুটি ডাটাবেসের সাথে একসাথে কাজ করা হচ্ছে: একটি MySQL ডাটাবেস এবং একটি H2 ডাটাবেস।
১. Maven ডিপেনডেন্সি
pom.xml ফাইলে প্রয়োজনীয় ডিপেনডেন্সি যুক্ত করতে হবে:
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Starter Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- H2 Database for testing -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
২. application.properties কনফিগারেশন
application.properties ফাইলে দুটি ডাটাবেসের কনফিগারেশন করা হবে:
# MySQL DataSource Configuration
spring.datasource.mysql.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.mysql.username=root
spring.datasource.mysql.password=root
spring.datasource.mysql.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.jpa.hibernate.ddl-auto=update
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
# H2 DataSource Configuration
spring.datasource.h2.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
spring.datasource.h2.driverClassName=org.h2.Driver
spring.datasource.h2.username=sa
spring.datasource.h2.password=password
spring.datasource.h2.dialect=org.hibernate.dialect.H2Dialect
এখানে, spring.datasource.mysql দিয়ে MySQL ডাটাবেস এবং spring.datasource.h2 দিয়ে H2 ইন-মেমরি ডাটাবেস কনফিগার করা হয়েছে।
৩. Multiple DataSource Configuration Setup
Spring Boot-এ @Configuration ক্লাস ব্যবহার করে একাধিক DataSource, EntityManagerFactory, এবং TransactionManager কনফিগার করতে হবে।
DataSourceConfig.java
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.example.repository.mysql", // MySQL Repository Package
entityManagerFactoryRef = "mysqlEntityManagerFactory",
transactionManagerRef = "mysqlTransactionManager"
)
public class MySQLDataSourceConfig {
@Primary
@Bean(name = "mysqlDataSource")
public DataSource mysqlDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
@Primary
@Bean(name = "mysqlEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
@Qualifier("mysqlDataSource") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setPackagesToScan("com.example.model"); // Model package for JPA
return factoryBean;
}
@Primary
@Bean(name = "mysqlTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("mysqlEntityManagerFactory") LocalContainerEntityManagerFactoryBean entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory.getObject());
return transactionManager;
}
}
H2DataSourceConfig.java
@Configuration
@EnableJpaRepositories(
basePackages = "com.example.repository.h2", // H2 Repository Package
entityManagerFactoryRef = "h2EntityManagerFactory",
transactionManagerRef = "h2TransactionManager"
)
public class H2DataSourceConfig {
@Bean(name = "h2DataSource")
public DataSource h2DataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1");
dataSource.setUsername("sa");
dataSource.setPassword("password");
return dataSource;
}
@Bean(name = "h2EntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
@Qualifier("h2DataSource") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setPackagesToScan("com.example.model"); // Model package for JPA
return factoryBean;
}
@Bean(name = "h2TransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("h2EntityManagerFactory") LocalContainerEntityManagerFactoryBean entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory.getObject());
return transactionManager;
}
}
এখানে, MySQLDataSourceConfig এবং H2DataSourceConfig দুটি আলাদা কনফিগারেশন ক্লাস তৈরি করা হয়েছে, যেখানে দুইটি আলাদা ডাটাবেসের জন্য DataSource, EntityManagerFactory, এবং TransactionManager কনফিগার করা হয়েছে।
৪. Entity এবং Repository তৈরি করা
একটি Entity ক্লাস এবং Repository ইন্টারফেস তৈরি করা।
Employee.java (Entity)
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Employee {
@Id
private Long id;
private String name;
// Getters and Setters
}
EmployeeRepository.java (Repository for MySQL)
import org.springframework.data.jpa.repository.JpaRepository;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
সারাংশ
Multiple DataSource কনফিগারেশন Spring Boot অ্যাপ্লিকেশনে একাধিক ডাটাবেস ব্যবহার করার জন্য গুরুত্বপূর্ণ। Spring Data JPA এবং @Configuration ক্লাস ব্যবহার করে বিভিন্ন ডাটাবেসের জন্য
Spring Boot-এর মাধ্যমে একটি অ্যাপ্লিকেশনে একাধিক ডাটাবেস সংযোগ (Multiple DataSource) কনফিগার করা যেতে পারে। এই ধরনের কনফিগারেশন তখন ব্যবহৃত হয় যখন আপনি একটি অ্যাপ্লিকেশনে একাধিক ডাটাবেসের সাথে কাজ করতে চান, যেমন একটি রিলেশনাল ডাটাবেস (MySQL/PostgreSQL) এবং একটি NoSQL ডাটাবেস (MongoDB) বা একাধিক রিলেশনাল ডাটাবেস।
Spring Boot এ Multiple DataSource কনফিগার করার জন্য কিছু গুরুত্বপূর্ণ পদক্ষেপ রয়েছে, যেমন:
- Multiple DataSource কনফিগারেশন তৈরি করা
- DataSource Bean তৈরি করা
- EntityManagerFactory কনফিগার করা
- Transaction Manager কনফিগার করা
- Repository কনফিগারেশন
এখানে আমরা দুটি ডাটাবেস (যেমন MySQL এবং PostgreSQL) কনফিগার করার উদাহরণ দেখবো।
১. Multiple DataSource কনফিগারেশন তৈরি করা
প্রথমে, application.properties বা application.yml ফাইলে দুটি ডাটাবেসের কনফিগারেশন যুক্ত করতে হবে।
application.properties-এ কনফিগারেশন:
# Primary DataSource (MySQL)
spring.datasource.primary.url=jdbc:mysql://localhost:3306/primarydb
spring.datasource.primary.username=root
spring.datasource.primary.password=root
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.primary.jpa.hibernate.ddl-auto=update
spring.datasource.primary.jpa.show-sql=true
# Secondary DataSource (PostgreSQL)
spring.datasource.secondary.url=jdbc:postgresql://localhost:5432/secondarydb
spring.datasource.secondary.username=postgres
spring.datasource.secondary.password=postgres
spring.datasource.secondary.driver-class-name=org.postgresql.Driver
spring.datasource.secondary.jpa.hibernate.ddl-auto=update
spring.datasource.secondary.jpa.show-sql=true
এখানে, দুটি ডাটাবেসের জন্য আলাদা কনফিগারেশন তৈরি করা হয়েছে: primary (MySQL) এবং secondary (PostgreSQL)।
২. DataSource Bean তৈরি করা
আমরা Primary DataSource এবং Secondary DataSource কনফিগার করতে দুটি আলাদা DataSource Bean তৈরি করব। প্রতিটি ডাটাবেসের জন্য আলাদা কনফিগারেশন এবং DataSource Bean তৈরি করা হয়।
Primary DataSource Configuration:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
@Configuration
public class PrimaryDataSourceConfig {
@Value("${spring.datasource.primary.url}")
private String url;
@Value("${spring.datasource.primary.username}")
private String username;
@Value("${spring.datasource.primary.password}")
private String password;
@Value("${spring.datasource.primary.driver-class-name}")
private String driverClassName;
@Bean
@Primary
public DataSource primaryDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName(driverClassName);
return dataSource;
}
}
Secondary DataSource Configuration:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class SecondaryDataSourceConfig {
@Value("${spring.datasource.secondary.url}")
private String url;
@Value("${spring.datasource.secondary.username}")
private String username;
@Value("${spring.datasource.secondary.password}")
private String password;
@Value("${spring.datasource.secondary.driver-class-name}")
private String driverClassName;
@Bean
public DataSource secondaryDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName(driverClassName);
return dataSource;
}
}
এখানে আমরা Primary DataSource এবং Secondary DataSource দুটি আলাদা Bean তৈরি করেছি।
৩. EntityManagerFactory কনফিগার করা
প্রতিটি ডাটাবেসের জন্য আলাদা EntityManagerFactory Bean তৈরি করতে হবে। এটি JPA ব্যবহার করে ডেটা ম্যানেজমেন্টের জন্য ব্যবহৃত হয়।
Primary EntityManagerFactory:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
public class PrimaryEntityManagerFactory {
private final DataSource primaryDataSource;
public PrimaryEntityManagerFactory(DataSource primaryDataSource) {
this.primaryDataSource = primaryDataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(primaryDataSource);
factoryBean.setPackagesToScan("com.example.primary"); // Scan for entities in this package
factoryBean.setPersistenceUnitName("primaryPU");
return factoryBean;
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
Secondary EntityManagerFactory:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
@Configuration
public class SecondaryEntityManagerFactory {
private final DataSource secondaryDataSource;
public SecondaryEntityManagerFactory(DataSource secondaryDataSource) {
this.secondaryDataSource = secondaryDataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(secondaryDataSource);
factoryBean.setPackagesToScan("com.example.secondary"); // Scan for entities in this package
factoryBean.setPersistenceUnitName("secondaryPU");
return factoryBean;
}
@Bean
public PlatformTransactionManager secondaryTransactionManager(EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
এখানে, PrimaryEntityManagerFactory এবং SecondaryEntityManagerFactory দুটি আলাদা EntityManagerFactory Bean তৈরি করা হয়েছে, যেগুলি তাদের respective DataSource-এ কাজ করবে।
৪. Repository কনফিগারেশন
Spring Data JPA-তে, আমরা @EnableJpaRepositories অ্যানোটেশন ব্যবহার করে JpaRepository এর জন্য আলাদা কনফিগারেশন প্রদান করি। প্রতিটি DataSource এবং EntityManagerFactory এর জন্য আলাদা JPA Repositories কনফিগার করতে হয়।
Primary Repository Configuration:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@Configuration
@EnableJpaRepositories(basePackages = "com.example.primary", entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager")
public class PrimaryRepositoryConfig {
}
Secondary Repository Configuration:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@Configuration
@EnableJpaRepositories(basePackages = "com.example.secondary", entityManagerFactoryRef = "secondaryEntityManagerFactory", transactionManagerRef = "secondaryTransactionManager")
public class SecondaryRepositoryConfig {
}
এখানে, প্রতিটি রেপোজিটরি কনফিগারেশন পৃথক EntityManager এবং TransactionManager ব্যবহার করে ডাটাবেসে ডেটা অপারেশন করবে।
৫. Usage in Service Layer
এখন আপনি Primary এবং Secondary ডাটাবেস থেকে ডেটা এক্সেস করতে Service Layer ব্যবহার করতে পারেন।
উদাহরণ: Service Layer
@Service
public class EmployeeService {
@Autowired
private PrimaryEmployeeRepository primaryEmployeeRepository;
@Autowired
private SecondaryEmployeeRepository secondaryEmployeeRepository;
public void saveEmployeeInPrimaryDb(Employee employee) {
primaryEmployeeRepository.save(employee);
}
public void saveEmployeeInSecondaryDb(Employee employee) {
secondaryEmployeeRepository.save(employee);
}
}
সারাংশ
Spring Boot Multiple DataSource Configuration আপনাকে একটি অ্যাপ্লিকেশনে একাধিক ডাটাবেসের সাথে কাজ করতে সক্ষম করে। আপনি Primary DataSource এবং Secondary DataSource কনফিগার করে তাদের জন্য আলাদা EntityManagerFactory, TransactionManager, এবং JpaRepository কনফিগারেশন করতে পারেন। এইভাবে, আপনি Spring Boot অ্যাপ্লিকেশনগুলোতে একাধিক ডাটাবেসের সাপোর্ট যোগ করতে পারেন এবং সহজে তাদের মধ্যে ডেটা অপারেশন পরিচালনা করতে পারেন।
Spring Boot JPA ব্যবহারের মাধ্যমে সাধারণত একটি ডেটাবেসের সাথে কাজ করা হয়, তবে কিছু অ্যাপ্লিকেশনে একাধিক ডেটাবেস ব্যবহার করার প্রয়োজন হতে পারে। এই পরিস্থিতিতে Multiple DataSource Configuration ব্যবহার করা হয়।
Spring Boot এ Multiple DataSource কনফিগারেশনের মাধ্যমে আপনি একাধিক ডেটাবেসের সাথে সংযোগ স্থাপন এবং পরিচালনা করতে পারেন। স্প্রিং বুটের এই বৈশিষ্ট্যটি একটি অ্যাপ্লিকেশনকে একাধিক ডেটাবেসে ডেটা অ্যাক্সেস করতে সক্ষম করে।
এই টিউটোরিয়ালে আমরা শিখব কীভাবে Multiple DataSource কনফিগার করা যায় এবং Spring Data JPA ব্যবহারের মাধ্যমে একাধিক ডেটাবেসের সাথে ইন্টারঅ্যাক্ট করা যায়।
Multiple DataSource কনফিগারেশন এর ধারণা
স্প্রিং বুটে একাধিক ডেটাবেস কনফিগার করার জন্য আপনাকে আলাদা DataSource কনফিগারেশন তৈরি করতে হবে, এবং প্রতিটি ডেটাবেসের জন্য EntityManagerFactory, TransactionManager এবং Repository কনফিগার করতে হবে।
1. First DataSource Configuration
প্রথম ডেটাবেসের জন্য ডেটাসোর্স কনফিগারেশন।
2. Second DataSource Configuration
দ্বিতীয় ডেটাবেসের জন্য আলাদা কনফিগারেশন।
3. @Primary ও @Qualifier ব্যবহার করা
ডিফল্ট DataSource নির্বাচন করার জন্য @Primary এবং বিশেষ DataSource নির্বাচন করতে @Qualifier ব্যবহার করা হয়।
উদাহরণ: Multiple DataSource কনফিগারেশন
এই উদাহরণে, আমরা দুইটি ডেটাবেস কনফিগার করব: একটি MySQL ডেটাবেস এবং একটি PostgreSQL ডেটাবেস।
1. application.properties কনফিগারেশন
প্রথমে, application.properties ফাইলে ডেটাবেস কনফিগারেশন যুক্ত করতে হবে।
application.properties
# Primary DataSource - MySQL configuration
spring.datasource.primary.url=jdbc:mysql://localhost:3306/primary_db
spring.datasource.primary.username=root
spring.datasource.primary.password=password
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.primary.jpa.hibernate.ddl-auto=update
spring.datasource.primary.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
# Secondary DataSource - PostgreSQL configuration
spring.datasource.secondary.url=jdbc:postgresql://localhost:5432/secondary_db
spring.datasource.secondary.username=postgres
spring.datasource.secondary.password=password
spring.datasource.secondary.driver-class-name=org.postgresql.Driver
spring.datasource.secondary.jpa.hibernate.ddl-auto=update
spring.datasource.secondary.jpa.database-platform=org.hibernate.dialect.PostgreSQL95Dialect
এখানে, দুটি ডেটাবেসের জন্য আলাদা কনফিগারেশন দেয়া হয়েছে: প্রথমটি MySQL এবং দ্বিতীয়টি PostgreSQL।
2. First DataSource Configuration
প্রথম ডেটাবেস কনফিগারেশনের জন্য @Configuration ক্লাস তৈরি করতে হবে। এখানে MySQL ডেটাবেসের জন্য কনফিগারেশন দেয়া হবে।
PrimaryDataSourceConfig.java
package com.example.springbootjpamultiple.datasource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
public class PrimaryDataSourceConfig {
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource dataSource() {
return new DriverManagerDataSource();
}
@Primary
@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
@Qualifier("primaryDataSource") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setPackagesToScan("com.example.springbootjpamultiple.model");
return factoryBean;
}
@Primary
@Bean(name = "transactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("entityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
এখানে, PrimaryDataSourceConfig ক্লাসে প্রথম ডেটাবেসের জন্য DataSource, EntityManagerFactory এবং TransactionManager কনফিগার করা হয়েছে।
3. Second DataSource Configuration
এখন, দ্বিতীয় ডেটাবেসের জন্য কনফিগারেশন তৈরি করতে হবে। এখানে PostgreSQL ডেটাবেসের জন্য কনফিগারেশন দেয়া হবে।
SecondaryDataSourceConfig.java
package com.example.springbootjpamultiple.datasource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
@Configuration
public class SecondaryDataSourceConfig {
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource dataSource() {
return new DriverManagerDataSource();
}
@Bean(name = "secondaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
@Qualifier("secondaryDataSource") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setPackagesToScan("com.example.springbootjpamultiple.model");
return factoryBean;
}
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
এখানে, SecondaryDataSourceConfig ক্লাসে দ্বিতীয় ডেটাবেসের জন্য DataSource, EntityManagerFactory এবং TransactionManager কনফিগার করা হয়েছে।
4. Entity Class
ডেটাবেসে সংরক্ষিত ডেটার জন্য একটি Entity ক্লাস তৈরি করতে হবে। এই Entity কেবল একটি ডেটাবেসের জন্য নয়, বরং আমাদের প্রোজেক্টে একাধিক ডেটাবেসের জন্য ব্যবহৃত হবে।
Employee.java
package com.example.springbootjpamultiple.model;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Employee {
@Id
private Long id;
private String name;
private String department;
// Getters and Setters
}
এখানে, Employee ক্লাস একটি সাধারণ Entity ক্লাস, যা id, name, এবং department ফিল্ড ধারণ করছে।
5. Repository Interface
EmployeeRepository তৈরি করতে হবে, যা Spring Data JPA ব্যবহার করে ডেটাবেসের সাথে CRUD অপারেশন করবে।
EmployeeRepository.java
package com.example.springbootjpamultiple.repository;
import com.example.springbootjpamultiple.model.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
// Custom query methods can be added here if needed
}
এই ক্লাসটি JpaRepository<Employee, Long> এক্সটেন্ড করেছে, যার মাধ্যমে Employee Entity এর জন্য CRUD অপারেশনগুলো সহজে পরিচালিত হবে।
6. Service Layer
স্প্রিং বুট অ্যাপ্লিকেশনের মধ্যে Business Logic সাধারণত Service Layer এ থাকে।
EmployeeService.java
package com.example.springbootjpamultiple.service;
import com.example.springbootjpamultiple.model.Employee;
import com.example.springbootjpamultiple.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class EmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
public List<Employee> getAllEmployees() {
return employeeRepository.findAll();
}
public Employee createEmployee(Employee employee) {
return employeeRepository.save(employee);
}
}
7. Controller Layer
এখন, RESTful API এর জন্য একটি Controller তৈরি করতে হবে যা HTTP রিকোয়েস্ট হ্যান্ডল করবে।
EmployeeController.java
package com.example.springbootjpamultiple.controller;
import com.example.springbootjpamultiple.model.Employee;
import com.example.springbootjpamultiple.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/employees")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@GetMapping
public List<Employee> getAllEmployees() {
return employeeService.getAllEmployees();
}
@PostMapping
public Employee createEmployee(@RequestBody Employee employee) {
return employeeService.createEmployee(employee);
}
}
এখানে, GET /employees এবং POST /employees রিকোয়েস্ট হ্যান্ডলিং করা হয়েছে।
সারাংশ
এটি ছিল Spring Boot এবং JPA ব্যবহার করে Multiple DataSource কনফিগার করার উদাহরণ। একাধিক ডেটাবেসে ডেটা অ্যাক্সেসের জন্য আলাদা DataSource, EntityManagerFactory, TransactionManager কনফিগারেশন করতে হয়। এই কনফিগারেশনগুলো স্প্রিং বুটের মাধ্যমে সহজেই বাস্তবায়ন করা সম্ভব এবং এটি সিস্টেমের স্কেলেবিলিটি এবং কার্যক্ষমতা বাড়াতে সাহায্য করে।
Read more